﻿using Fabrication.Exceptions;
using NUnit.Framework;

namespace Fabrication.Tests
{
    [TestFixture]
    public class link_details
    {
        [Test]
        public void should_return_unmodified_value_if_modifying_function_not_supplied()
        {
            var linkDetails = new LinkDetails(typeof(link_details), typeof(link_details), typeof(string), "Source", "Target");
            linkDetails.SetSourceValue("Value");

            Assert.That(linkDetails.GetTargetValue(), Is.EqualTo("Value"));
        }

        [Test]
        public void should_return_modified_value_if_modifying_function_is_supplied()
        {
            var linkDetails = new LinkDetails(typeof(link_details), typeof(link_details), typeof(string), "Source", "Target", x => string.Format("Modified-{0}", x));
            linkDetails.SetSourceValue("Value");

            Assert.That(linkDetails.GetTargetValue(), Is.EqualTo("Modified-Value"));
        }

        [Test]
        public void should_fail_if_any_required_parameter_is_null()
        {
            Assert.Throws<LinkedPropertyException>(() => new LinkDetails(null, typeof(link_details), typeof(string), "Source", "Target"));
            Assert.Throws<LinkedPropertyException>(() => new LinkDetails(typeof(link_details), null, typeof(string), "Source", "Target"));
            Assert.Throws<LinkedPropertyException>(() => new LinkDetails(typeof(link_details), typeof(link_details), null, "Source", "Target"));
            Assert.Throws<LinkedPropertyException>(() => new LinkDetails(typeof(link_details), typeof(link_details), typeof(string), null, "Target"));
            Assert.Throws<LinkedPropertyException>(() => new LinkDetails(typeof(link_details), typeof(link_details), typeof(string), "Source", null));
        }

        [Test]
        public void should_fail_if_either_property_name_is_empty()
        {
            Assert.Throws<LinkedPropertyException>(() => new LinkDetails(typeof(link_details), typeof(link_details), typeof(string), "", "Target"));
            Assert.Throws<LinkedPropertyException>(() => new LinkDetails(typeof(link_details), typeof(link_details), typeof(string), "Source", ""));
            Assert.Throws<LinkedPropertyException>(() => new LinkDetails(typeof(link_details), typeof(link_details), typeof(string), "   ", "Target"));
            Assert.Throws<LinkedPropertyException>(() => new LinkDetails(typeof(link_details), typeof(link_details), typeof(string), "Source", "   "));
        }

        [Test]
        public void should_fail_if_value_is_retrieved_before_being_set()
        {
            var linkDetails = new LinkDetails(typeof(link_details), typeof(link_details), typeof(string), "Source", "Target");

            Assert.Throws<LinkedPropertyException>(() => linkDetails.GetTargetValue());
        }

        [Test]
        public void should_fail_if_source_is_incorrect_type()
        {
            var linkDetails = new LinkDetails(typeof(string), typeof(string), typeof(string), "Source", "Target");

            Assert.Throws<LinkedPropertyException>(() => linkDetails.SetSourceValue(100));
        }
    }
}
